package dao.impl;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.persistence.EntityManager;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

import dao.interf.IBaseDAO;

public class BaseDAO<T> implements IBaseDAO<T> {

	public String POJOCLASS = "";
	public String TABLENAME = "";
	
	private SessionFactory sessionFactory;
	

	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	public BaseDAO() {
		Type genType = this.getClass().getGenericSuperclass();
		Type[] params = ((ParameterizedType) genType).getActualTypeArguments();

		if (null == params || 0 == params.length) {
			return;
		}
		POJOCLASS = params[0].toString();
		POJOCLASS = POJOCLASS.substring(POJOCLASS.indexOf(' ') + 1);
		int x = POJOCLASS.lastIndexOf(".");
		if (x >= 0) {
			TABLENAME = POJOCLASS.substring(x + 1);
		} else {
			TABLENAME = POJOCLASS;
		}

	}
	//============================== persist method ====================================
	public void batchAdd(List<T> entities) throws RuntimeException {
		Session sess = sessionFactory.openSession();
		Transaction tx = sess.getTransaction();
		try {
			tx.begin();
			for(T e : entities) {
				sess.persist(e);
			}
			sess.flush();
			sess.clear();
			tx.commit();
		} catch (HibernateException hbe) {
			tx.rollback();
			throw hbe;
		} finally {
			if(null != sess) {
				sess.close();
			}
		}
		//debug pass
	}

	public void batchDel(List<T> entities) throws RuntimeException {
		Session sess = sessionFactory.openSession();
		Transaction tx = sess.getTransaction();
		try {
			tx.begin();
			for(T e : entities) {
				sess.delete(e);
			}
			tx.commit();
		} catch (HibernateException hbe) {
			tx.rollback();
			throw hbe;
		} finally {
			if(null != sess) {
				sess.close();
				sess = null;
			}
		}
		System.out.println("batch del success");
	}

	public void batchUpdate(List<T> entities) throws RuntimeException {
		Session sess = sessionFactory.openSession();
		Transaction tx = sess.getTransaction();
		try {
			tx.begin();
			for(T e : entities) {
				sess.merge(e);
			}
			sess.flush();
			sess.clear();
			tx.commit();
		} catch (HibernateException hbe) {
			tx.rollback();
			throw hbe;
		} finally {
			if(null != sess) {
				sess.close();
				sess = null;
			}
		}
		
	}
	
	public void batchSave(List<T> entities) throws RuntimeException {
		Session sess = sessionFactory.openSession();
		Transaction tx = sess.getTransaction();
		try {
			tx.begin();
			for(T e : entities) {
				sess.persist(e);
			}
			sess.flush();
			sess.clear();
			tx.commit();
		} catch (HibernateException hbe) {
			tx.rollback();
			throw hbe;
		} finally {
			if(null != sess) {
				sess.close();
				sess = null;
			}
		}
	}
	
	/**
	 * 删除实体
	 * @throws RuntimeException
	 */
	public void del(T entity) throws RuntimeException {
		if(null == entity) {
			return;
		}
		Session sess = sessionFactory.openSession();
		Transaction tx = sess.getTransaction();
		try {
			tx.begin();
			sess.delete(entity);
			tx.commit();
		} catch (HibernateException hbe) {
			tx.rollback();
			throw hbe;
		} finally {
			if(null != sess) {
				sess.close();
				sess = null;
			}
		}
		
		//debug pass
	}
	
	/**
	 * 删除entity通过id
	 * @param id
	 * 			entity id
	 * @throws RuntimeException
	 */
	public void delById(Object id) throws RuntimeException {
		del(findById(id));
		//debug pass
	}

	/**
	 * 全部删除表中的记录
	 */
	public void delAll() throws RuntimeException {
		Session sess = sessionFactory.openSession();
		String hql = "DELETE FROM " + TABLENAME;
		Transaction tx = sess.getTransaction();
		try {
			tx.begin();
			Query query = sess.createQuery(hql);//会自动和数据库中的表匹配删除(Member->Members)。
			query.executeUpdate();
			tx.commit();
		} catch (HibernateException hbe) {
			tx.rollback();
			throw hbe;
		} finally {
			sess.close();
			sess = null;
		}
		//debug pass
	}

	/**
	 * 查找所有字段
	 * 
	 * @param Rule
	 *            查找规则
	 * @return entities 实体集合
	 * @throws RuntimeException
	 */
	public List<T> findAll() throws RuntimeException {
		Session sess = sessionFactory.openSession();
		Query query = null;	
		List<T> entities = new ArrayList<T>(0);
		try {
			query  = sess.createQuery("FROM " + TABLENAME); 
			entities = query.list();
		} finally {
			if(null != sess) {
				sess.close();
				sess = null;
			}
		}
		//debug pass
		return entities;
	}

	/**
	 * 查询实体,通过id
	 * 
	 * @param id
	 *            实体id
	 * @return entity 实体
	 * @throws RuntimeException
	 */
	@SuppressWarnings("unchecked")
	public T findById(Object id) throws RuntimeException {
		Session sess = sessionFactory.openSession();
		T entity = null;
		try {
			entity = (T) sess.get(Class.forName(POJOCLASS), (Integer)id);
		} catch (ClassNotFoundException e) {
			throw new RuntimeException(e);
		} finally {
			if(null != sess) {
				sess.close();
				sess = null;
			}
		}
		//debug pass
		return entity;
	}
	
	//hibernate3
	public T save(T entity) throws RuntimeException {
		
		Session sess = sessionFactory.openSession();
		Transaction tx = sess.getTransaction();
		try {
			tx.begin();
			sess.save(entity);
			tx.commit();
		} catch (HibernateException hbe) {
			tx.rollback();
			throw hbe;
		} finally {
			if(null != sess) {
				sess.close();
				sess = null;
			}
		}
		//debug pass
		System.out.println("Save one success");
		return entity;
	}
	

	/**
	 * 更新实体
	 * @return entity
	 * @throws RuntimeExcption
	 */
	public T update(T entity) throws RuntimeException {
		Session sess = sessionFactory.openSession();
		
		Transaction tx = sess.getTransaction();
		try {
			tx.begin();
			sess.saveOrUpdate(entity);
			tx.commit();
		} catch (HibernateException hbe) {
			tx.rollback();
			throw hbe;	
		} finally {
			if(null != sess) {
				sess.close();
				sess = null;
			}
		}
		//debug pass
		return entity;
	}

	/**
	 * 获取所有记录数
	 * 
	 * @return 记录数
	 * @throws RuntimeException
	 */
	public Integer getAllCount() throws RuntimeException {
		List<T> lst = findAll();
		return lst.size();
	}

	/**
	 * 查找一组实体，通过给出的属性
	 * @param pNames
	 * 			属性名
	 * @param pValues
	 * 			值
	 * @throws RuntimeException
	 */
	public List<T> findByProperties(String[] pNames, Object[] pValues)
			throws RuntimeException {
		if (pNames.length == 0) {
			return findAll();
		}
		String queryString = "FROM " + TABLENAME
				+ " WHERE " + pNames[0] + "= ?";
		for (int i = 1; i < pNames.length; i++) {
			queryString += " AND " + pNames[i] + "= ?";
		}
		return find(queryString, pValues);
	}
	
	/**
	 * select
	 * @param queryString:需要查找的query串
	 * @param pvalues:参数值数组
	 * @return 返回的结果列表 
	 */
	public List<T> find(String queryString, Object[] pvalues){
		System.out.println(queryString);
		Session sess = sessionFactory.openSession();
		Query query =  null;
		List<T> lst = new ArrayList<T>(0);
		try {
			query = sess.createQuery(queryString);
			int len = pvalues.length;
			for(int i = 0; i < len; i++) {
				query.setParameter(i, pvalues[i]);
			}
			lst = query.list(); 
		} finally {
			if(null != sess) {
				sess.close();
				sess = null;
			}
		}
		return lst;
	}
	/**
	 * 
	 * @param queryString:需要查找的query串
	 * @return 返回的结果列表 
	 */
	public List<T> find(String queryString){
		Session sess = sessionFactory.openSession();
		List<T> lst = new ArrayList<T> (0);
		try {
			Query query =  sess.createQuery(queryString);
			lst = query.list();
		} finally {
			if(null != sess) {
				sess.close();
				sess = null;
			}
		}
		return lst;
	}

	/* 通过属性删除
	 * @see dao.interf.IBaseDAO#delByProperties(java.util.Map)
	 */
	public int delByProperties(final Map<String, Object> map)
			throws RuntimeException {
		Session sess = sessionFactory.openSession();
		String queryString = "delete from " + TABLENAME + " model";
		Iterator<Entry<String,Object>> l = map.entrySet().iterator();
		Entry<String,Object> e = null;
		if (l.hasNext()) {
			e = l.next();
			queryString += " where model." + e.getKey() + " = :"
					+ e.getKey();
		}
		int i = 2;
		for (; l.hasNext(); i++) {
			e = l.next();
			queryString += " and model." + e.getKey() + " = :"
					+ e.getKey();
		}
		int x = 0;
		try {
			Query queryObject = sess.createQuery(queryString);
			for (l = map.entrySet().iterator(); l.hasNext();) {
				e = l.next();
				queryObject.setParameter((String) e.getKey(), e.getValue());
			}
			x = queryObject.executeUpdate();
		} finally {
			if(null != sess) {
				sess.close();
				sess = null;
			}
		}
		return x;//删除记录的个数
	}
	
	public List<T> findByProperties(final Map<String,Object> map) throws RuntimeException {
		Session sess = sessionFactory.openSession();
		Iterator<Entry<String,Object>> l = map.entrySet().iterator();
		Entry<String,Object> e = null;
		String queryString = " FROM " + TABLENAME + " model";
		if (l.hasNext()) {
			e = l.next();
			queryString += " where model." + e.getKey() + " = :"
					+ e.getKey();
		}
		int i = 2;
		for (; l.hasNext(); i++) {
			e = l.next();
			queryString += " and model." + e.getKey() + " = :"
					+ e.getKey();
		}
		List<T> lst = null;
		try {
			Query queryObject = sess.createQuery(queryString);
			for (l = map.entrySet().iterator(); l.hasNext();) {
				e = l.next();
				queryObject.setParameter((String) e.getKey(), e.getValue());
			}
			lst = queryObject.list();
		} finally {
			if(null != sess) {
				sess.close();
				sess = null;
			}
		}
		return lst;
	}
	
}
